home *** CD-ROM | disk | FTP | other *** search
- /* I have adapted Clay Davis' modification of Peter Thomas' adaptation
- of David Dubois' BASIC routines found on CompuServe. (whew!) Believe
- it or not, the Microsoft C version compiled and ran WITHOUT ERROR
- and WITHOUT MODIFICATION under Power C 2.2.0. I have included these
- functions in my CJSLIB function library, and am indebted to the above
- mentioned individuals for their willingness to share their techniques.
-
- Chuck Steenburgh [72330,1776] */
-
- /*****************************************************************************
- This is a version of GLBL.ARC which was slightly modified to be used
- in Microsoft-C. The following changes were made:
-
- 1. All calls to _farmalloc were replaced with _fmalloc
- 2. All calls to _farfree were replaced with _ffree
- 3. MS-C does not have an _mk_fp function which converts a pointer to
- a far pointer. So, this task was done by multiplying the segment by
- 0x10000 to shift the pointer.
-
- Other than these changes (Isn't C portable), the routine runs as stated
- in the MS-C medium model. Other models should work also.
-
- Modified by Clay Davis 76346,101 on July 11, 1988. Tested using MS-C 5.1.
-
- ************************************************************************
-
- This code is based upon the program SETPATH.PAS (located in BPROGA) by
- David Dubois [71401,747]
-
- This Turbo C version is written by Peter Thomas [75716,2377]
-
- This series of routines are designed to Locate, Retrieve, Update, and
- Remove "Variables" from the MASTER copy of the DOS Environment table.
- The routines have been written in a manner that avoids linking any
- EXTERNAL routines for string manipulation, and thus should be independent
- of memory model being used.
-
- Be careful that changes made to the Environment with these routines
- ONLY OCCUR IN THE MASTER COPY, and that if COMMAND.COM is spawned
- from a routine that has changed the environment, NO CHANGES WILL BE
- SEEN IN THE ENVIRONMENT. This is most apparent when this program is run
- in the INTEGRATED environment: changes made by this technique will
- not appear if the "OS Shell" is invoked, and will only appear on exit
- from TC.
-
- For full documentation on the techniques used here can be found in the
- file COMENV.ARC located in LIB 2 of BPROGA on Compuserve.
-
- As David Dubois says:
-
- I hereby dedicate this knowledge to the public domain. Feel free to use
- it, but if you do, please mention my name. There are no guarantees, and
- in fact, I wouldn't bet a dollar that it will work every time.
-
- That this works at all is based on experimental, rather than properly
- documented, evidence. There are no guarantees. But then, its free.
-
- *****************************************************************************/
-
- #include <dos.h>
- #include <stdio.h> /* MS-C requires this */
- #include <stdlib.h> /* MS-C requires this */
- #include <malloc.h> /* MS-C uses this instead of alloc.h */
-
- /*
- * Mstr_FindEnvironment:
- * Scans for the "Master" Environment area, and returns
- * a pointer to it, and the size of the environment.
- */
-
- void Mstr_FindEnvironment ( char far **Env , unsigned *EnvSize )
- {
- unsigned int far *CommandSeg, far *TempSeg ;
- char far *BlockSeg ;
-
- /*
- * Scan through PSP's looking for a block that is its own father.
- * This block is the PSP of COMMAND.COM
- */
- TempSeg = _psp*0x10000; /* Convert to a far pointer, replaces MK_FP */
- do
- {
- CommandSeg = TempSeg ;
- TempSeg = *(TempSeg+8)*0x10000; /* Replaces MK_FP in turbo C */
- }
- while ( TempSeg != CommandSeg ) ;
-
- /*
- * Scan forward through memory looking for the correct MSB.
- * This will have COMMAND.COM's PSP as owner, and begin with
- * the character M
- */
- BlockSeg = (char far *)CommandSeg ;
- do
- {
- BlockSeg = (FP_SEG(BlockSeg)+1)*0x10000; /* Replaces MK_FP */
- }
- while ( ( *(unsigned int far *)(BlockSeg+1) != FP_SEG ( CommandSeg ) ) ||
- ( *BlockSeg != 'M' ) ) ;
-
- /*
- * The environment is the NEXT segment of memory
- * and bytes 4 and 5 are the size in paragraphs
- */
- *Env = (FP_SEG(BlockSeg)+1)*0x10000; /* Replaces MK_FP */
- *EnvSize = 16 * *(unsigned int far *)(BlockSeg+3) ;
- }
-
-
-
-
- /*
- * Mstr_getenv:
- * Scans the "Master" Environment for a given "sub string"
- * and returns a pointer to it.
- * Similar to Turbo routine "getenv" but uses the Master copy of the
- * environment table.
- */
-
- char far *Mstr_getenv (char far *Env , char far *name)
- {
- char far *Sub_Env, far *str1, far *str2 ;
-
- /*
- * Start at the beginning of the environment
- */
- Sub_Env = Env ;
-
- /*
- * While the "sub string" we're looking at is non-zero
- */
- for ( ; *Sub_Env ; )
- {
- /*
- * Simulate a "strcmp" on the "sub string" of the environment
- * and the string we're looking for
- */
- for ( str1 = Sub_Env , str2 = name ;
- (*str1) && (*str2) && ( *str1 == *str2) ;
- str1++ , str2++ ) ;
- /*
- * If we reached the end of the string we're looing for
- * we've found the correct portion of the environment.
- * Return the ptr to the start of this "sub string"
- */
- if ( !*str2 )
- return ( Sub_Env ) ;
-
- /*
- * Otherwise, advance to the next "sub string" in the environment
- * by performing a "strchr" function
- */
- for ( ; *(Sub_Env++) ; ) ;
- }
-
- /*
- * Obviously, the string is not present in the environment.
- * Return this fact.
- */
- return ( NULL ) ;
- }
-
-
-
-
- /*
- * Mstr_delenv:
- * Scans the "Master" Environment for a given "sub string"
- * and removes it.
- */
-
- int Mstr_delenv (char far *Env , unsigned EnvSize , char far *name)
- {
- char far *Sub_Env , far *New_Env ;
- char huge *Dest , far *Src , huge *End_Env ;
-
- int Done ;
- unsigned Ctr ;
-
- /*
- * Allocate a chunk of storage to act as a "working" copy of
- * the Environment table
- */
- New_Env = _fmalloc ( EnvSize ) ;
-
- /*
- * Copy the data from the Master to Working copy of the
- * Environment table.
- * Simulates a "memcpy" function.
- */
- for ( Src = Env , Dest = (char far *)New_Env , Ctr = 0 ;
- Ctr < EnvSize ;
- *(Dest++) = *(Src++) , Ctr++ ) ;
-
- /*
- * Scan the working copy of the environment for the desired
- * sub string
- */
- Sub_Env = Mstr_getenv ( New_Env , name ) ;
-
- if ( Sub_Env == NULL )
- {
- /*
- * If not found, do nothing
- */
- Done = -1 ;
- } else {
- /*
- * Locate the end of the string to delete
- * Simulate a "strchr" call
- */
- for ( Src = Sub_Env ; *(Src++) ; ) ;
-
- /*
- * Move the rest of the environment back over the "sub string"
- * being deleted.
- * Simulated "memcpy" function.
- * Huge pointers used for pointer comparison purposes.
- */
- for ( Dest = (char huge *)Sub_Env , End_Env = (char huge *) (New_Env + EnvSize ) ;
- ( Dest < End_Env ) ;
- *(Dest++) = *(Src++) ) ;
-
- /*
- * Copy the data from the Working to Master copy of the
- * Environment table.
- * Simulates a "memcpy" function.
- */
- for ( Src = New_Env , Dest = (char huge *)Env , Ctr = 0 ;
- Ctr < EnvSize ;
- *(Dest++) = *(Src++) , Ctr++ ) ;
-
- /*
- * Signal all done
- */
- Done = 0 ;
- }
-
- /*
- * Free all working storage
- */
- _ffree ( New_Env ) ;
-
- return ( Done ) ;
- }
-
-
-
-
- /*
- * Mstr_putenv:
- * Adds/Replaces a given "sub string" in the Master Environment.
- * Similar to Turbo routine "putenv" but uses the Master copy of the
- * environment table.
- */
-
- int Mstr_putenv (char far *Env , unsigned EnvSize , char far *name )
- {
- char far *Sub_Env , far *Temp_Name ;
- char huge *Dest , far *Src , huge *End_Env ;
- int Done ;
-
- /*
- * Allocate a chunk of storage to create the Variable name to add
- * to the Environment table
- */
- Temp_Name = _fmalloc ( 256 ) ;
-
- /*
- * Extract only the Name portion of the data to add to the Environment
- */
- for ( Src = name , Dest = Temp_Name ;
- *Src && ( *Src != '=' ) ;
- *(Dest++) = *(Src++) ) ;
-
- /*
- * Ensure that the resulting name is well formed.
- */
- *(Dest++) = '=' ;
- *Dest = 0 ;
-
- /*
- * Delete this sub string if found in the environment
- */
- Mstr_delenv ( Env , EnvSize , Temp_Name ) ;
-
- /*
- * Locate the END of the Master table by locating a zero length
- * String in it
- */
- Sub_Env = Env ;
- for ( ; *Sub_Env ; )
- {
- for ( ; *(Sub_Env++) ; ) ;
- }
-
- /*
- * Add the new string to the END of the existing environment, with
- * trincation IF needed
- */
- for ( Dest = (char huge *)(Sub_Env) , Src = name , End_Env = (char huge *) (Env + EnvSize ) ;
- ( Dest < End_Env ) && (*Src) ;
- *(Dest++) = *(Src++) ) ;
-
- Done = -1 ;
- if ( !*Src )
- {
- /*
- * If the string to add was FULLY added, ensure that the
- * newly updated environment is properly finished
- */
- Done = 0 ;
- *(Dest++) = 0 ;
- *Dest = 0 ;
- }
-
- /*
- * As a real safety measure, ensure that the FINAL two bytes of the
- * Environment are both 0. This will finish the last string AND
- * ensure that a zero length string is also present
- */
- *(End_Env-1) = 0 ;
- *(End_Env-2) = 0 ;
-
- /*
- * Free all working storage
- */
- _ffree ( Temp_Name ) ;
-
- return ( Done ) ;
- }
-